package com.honey.utils;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.codec.binary.Base64;
import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.honey.config.LogoConfig;
import com.honey.entity.TwoCode;

/**
 * 配置图像写入器
 *
 * @author 鱼乐
 *
 */
public class MatrixToImageWriter {
	
    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;

    private MatrixToImageWriter() {
    }
    
    /**
     * 图片文件
     * @param twoCode
     */
    public static void ToCodeFile(TwoCode twoCode) {
    	try {
            String content = twoCode.getCodeContent();
            String path = twoCode.getCodeCreateUrl();// 二维码保存的路径
            String codeName = twoCode.getCodeName();// 二维码的图片名
            String imageType = twoCode.getPicType();// 图片类型
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, String.valueOf(twoCode.getCodePadding())); // 设置边距
            hints.put(EncodeHintType.ERROR_CORRECTION, String.valueOf(twoCode.getCodeErr())); // 设置容错率为H级别（35%）
            BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, twoCode.getCodeSize(), twoCode.getCodeSize(), hints);
            File file1 = new File(path, codeName + "." + imageType);
            MatrixToImageWriter.writeToFile(bitMatrix, imageType, file1,twoCode);
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
    
    /**
     * 图片流
     * @param twoCode
     */
    public static String ToCodeBuf(TwoCode twoCode) {
    	BufferedImage imgBufferedImage = null;
    	String Base64Img = "";
    	try {
    		String content = twoCode.getCodeContent();
    		String imageType = twoCode.getPicType();// 图片类型
    		MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
    		Map<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>();
    		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    		hints.put(EncodeHintType.MARGIN, String.valueOf(twoCode.getCodePadding())); // 设置边距
    		hints.put(EncodeHintType.ERROR_CORRECTION, String.valueOf(twoCode.getCodeErr())); // 设置容错率为H级别（35%）
    		BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, twoCode.getCodeSize(), twoCode.getCodeSize(), hints);
    		imgBufferedImage = MatrixToImageWriter.imgToBuf(bitMatrix, imageType,twoCode);
    		Base64Img = toBase64(imgBufferedImage);
    	} catch (WriterException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}
		return Base64Img;
    }
    
    public static String toBase64(BufferedImage image) throws IOException {
        // 创建一个字节输出流来存储图片的字节数据
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 将BufferedImage写入到字节输出流中，选择合适的格式，如"png"或"jpg"
        javax.imageio.ImageIO.write(image, "png", baos); 
        baos.flush();
        byte[] imageInByte = baos.toByteArray();
        baos.close();
        // 使用Apache Commons Codec进行Base64编码
        return Base64.encodeBase64String(imageInByte);
    }
    

    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

    public static void writeToFile(BitMatrix matrix, String format, File file,TwoCode twoCode) throws IOException {
        BufferedImage image = toBufferedImage(matrix);
        
        //设置logo图标  
        if(twoCode.isLogoFlag()) {
        	LogoConfig logoConfig = new LogoConfig();  
            image = logoConfig.LogoMatrix(image,twoCode.getLogoUrl());
        }
        
        if(twoCode.isCodeFontFlag()) {
        	Graphics g = image.createGraphics();
            int width = matrix.getWidth();
            int height = matrix.getHeight();
            int fontSize = twoCode.getFontSize();
            //计算文字开始的位置
    	    //x开始的位置：（图片宽度-字体大小*字的个数）/2
    	    int startX = (width-(fontSize*twoCode.getCodeFontContent().length()))/2;
    	    //y开始的位置：图片高度-（图片高度-图片宽度）/2
    	    int startY = height-(height-width)/2;   
            g.drawImage(image, 0, 0, width, height, null);
            g.setColor(twoCode.getFontColor());
            g.setFont(new Font(null, 1, fontSize));
            g.drawString(twoCode.getCodeFontContent(), startX, startY-5);
            g.dispose();
        }
        
        if (!ImageIO.write(image, format, file)) {
            throw new IOException("Could not write an image of format " + format + " to " + file);
        }
    }
    
    public static BufferedImage imgToBuf(BitMatrix matrix, String format,TwoCode twoCode) throws IOException {
    	BufferedImage image = toBufferedImage(matrix);
    	
    	//设置logo图标  
    	if(twoCode.isLogoFlag()) {
    		LogoConfig logoConfig = new LogoConfig();  
        	image = logoConfig.LogoMatrix(image,twoCode.getLogoUrl());
    	}
    	
    	if(twoCode.isCodeFontFlag()) {
    		Graphics g = image.createGraphics();
        	int width = matrix.getWidth();
        	int height = matrix.getHeight();
        	int fontSize = twoCode.getFontSize();
        	//计算文字开始的位置
        	//x开始的位置：（图片宽度-字体大小*字的个数）/2
        	int startX = (width-(fontSize*twoCode.getCodeFontContent().length()))/2;
        	//y开始的位置：图片高度-（图片高度-图片宽度）/2
        	int startY = height-(height-width)/2;   
        	g.drawImage(image, 0, 0, width, height, null);
        	g.setColor(twoCode.getFontColor());
        	g.setFont(new Font(null, 1, fontSize));
        	g.drawString(twoCode.getCodeFontContent(), startX, startY-5);
        	g.dispose();
    	}
    	
    	return image;
    }

}
